package com.rambler.fileupload.processor;

import com.rambler.common.utils.FileUtil;
import com.rambler.common.utils.IDUtil;
import com.rambler.api.fileupload.dto.FileMetadata;
import com.rambler.api.fileupload.dto.FileUploadDTO;
import com.rambler.api.fileupload.dto.ImageProcessOption;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Objects;

/**
 * @author suhao
 * 图片处理单元
 */
@Component
public class ImageProcessor {

    /**
     * 处理图片
     * 支持压缩, 裁剪, 缩放, 转换格式
     *
     * @param dto 图片处理option
     */
    public MultipartFile processImage(MultipartFile file, FileUploadDTO dto) {

        // 图片处理选项
        ImageProcessOption option = dto.getImageProcessOption();
        FileMetadata fileMetadata = dto.getFileMetadata();

        assert file != null;
        String originalFileName = file.getOriginalFilename();
        String originalFileExtension = FileUtil.getExtension(Objects.requireNonNull(originalFileName));
        String finalExtension = option.getOutputFormat() == null ? originalFileExtension : option.getOutputFormat();
        String contentType = "image/" + finalExtension;
        // 图片处理可能会更改图片content-type, 这里覆盖一下
        fileMetadata.setContentType(contentType);
        fileMetadata.setExtension(finalExtension);

        BufferedImage original = null;
        try {
            // 1. 读取图片
            original = ImageIO.read(file.getInputStream());

            // 2. 裁剪
            ImageProcessOption.CropRegion crop = option.getCrop();
            if (null != crop) {
                original = original.getSubimage(crop.getCropX(), crop.getCropY(), crop.getCropWidth(), crop.getCropHeight());
            }

            // 3. 压缩
            Thumbnails.Builder<BufferedImage> bufferedImageBuilder = Thumbnails.of(original);
            if (option.getQuality() != 0) {
                bufferedImageBuilder.outputQuality(option.getQuality());
            }

            // 4. 缩放
            if (null != option.getResize()) {
                bufferedImageBuilder.size(option.getResize().getMaxWidth(), option.getResize().getMaxHeight());
            } else {
                bufferedImageBuilder.scale(1.0);
            }

            // 5. 转换格式
            if (null != option.getOutputFormat() && !option.getOutputFormat().isEmpty()) {
                bufferedImageBuilder.outputFormat(finalExtension);

            } else {
                bufferedImageBuilder.outputFormat(originalFileExtension);
            }

            ByteArrayOutputStream os = new ByteArrayOutputStream();
            bufferedImageBuilder.toOutputStream(os);

            // 6. 上传
            String uid = IDUtil.randomUUID();
            String fileName = uid + "." + finalExtension;
            return convert(os, fileName, contentType);

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 字节流转换为MultipartFile
     *
     * @param os               outputStream
     * @param fileName         文件名
     * @param contentType      文件类型
     * @return MultipartFile
     * @throws IOException 类型
     */
    public static MultipartFile convert(ByteArrayOutputStream os, String fileName, String contentType) throws IOException {
        return new MockMultipartFile(fileName, fileName, contentType, os.toByteArray());
    }
}
